package com.sinodata.bsm.cicp.collector.oracle;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.AbstractJDBCCollector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.DBConnectionUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 *
 * <p>
 * Description: 共享池空闲比率
 * </p>
 *
 * @author Chao.Liu
 * @version 3.1

 * <p>
 * History:
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2011-11-10 上午10:36:20          Chao.Liu        3.1         To create
 * </p>
 *
 * @since
 * @see
 */
public class SharedPoolFreeCollector extends AbstractJDBCCollector {
    private final Logger logger = Logger.getLogger(SharedPoolFreeCollector.class);

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        String[] propMetas = getPropMeta();
        try {
            String rsStr = this.getField(ip);
            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
            for (int i = 0; i < propMetas.length; i++) {
                propValues[i] = ResPropertyValue.createPropValue(rsStr, propMetas[i]);
            }
            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (Exception e) {
            logger.error("failed to collect oracle invalid indexes", e);
            throw new CollectorException(e);
        }
        return values;
    }

    private String getField(String ip) throws CollectorException {
        String dbname = this.getParamMap().get("DBName").trim();
        String dbtype = this.getParamMap().get("DBType").trim();

        CallableStatement cstmt = null;
        ResultSet rst = null;
        Connection conn = null;

        String sharedPoolFree = null;
        String sql = "";
        String sql_9i_befor = "select (v$sgastat.bytes / v$parameter.value) * 100 from v$sgastat, v$parameter where v$sgastat.name = 'free memory' and v$parameter.name = 'shared_pool_size' and v$sgastat.pool = 'shared pool'";
        String sql_10g_after = "select (v$sgastat.bytes / v$sgainfo.bytes) * 100 from v$sgastat, v$sgainfo where v$sgastat.name = 'free memory' and v$sgainfo.name = 'Shared Pool Size' and v$sgastat.pool = 'shared pool'";

        int version = OracleCollectorUtil.getVersion(dbtype, ip, dbname);
        if (version <= 9) {
            sql = sql_9i_befor;
        } else if (version >= 10) {
            sql = sql_10g_after;
        }

        try {
            conn = DBConnectionUtil.getInstance().getConnection(dbtype, ip, dbname);
            cstmt = conn.prepareCall(sql);
            rst = cstmt.executeQuery();

            if (rst != null && rst.next()) {
                sharedPoolFree = rst.getString(1);
            }

        } catch (SQLException sqle) {
            logger.error("Collecting oralce Shared Pool Free", sqle);
            throw new CollectorException(sqle);
        } catch (Exception ioex) {
            logger.error("Collecting oralce Shared Pool Free", ioex);
            throw new CollectorException(ioex);
        } finally {
            try {
                if (rst != null) {
                    rst.close();
                }
                if (cstmt != null) {
                    cstmt.close();
                }
                DBConnectionUtil.getInstance().returnConnection(conn);
            } catch (SQLException e) {
                logger.error("failed to close database", e);
                throw new CollectorException(e);
            }
        }

        sharedPoolFree = this.formatNumber(sharedPoolFree);

        return sharedPoolFree;
    }

    private String formatNumber(String num) {
        String s = "";
        Double d = new Double(num);

        NumberFormat nf = new DecimalFormat("#.00");
        s = nf.format(d);

        return s;
    }

    @Override
    public String[] getPropMeta() { // And the corresponding script
        return new String[] { "$1" };
    }

    @Override
    public String[] getParamMeta() { // These three parameters from the script
        return new String[] { "DBName", "DBType" };
    }

    public static void main(String[] args) {
        NumberFormat nf = new DecimalFormat("#.00");
        String s = nf.format(23.2132424);

        System.out.println(s);
    }
}
